package com.ly.hotel.webagent;

import android.util.Log;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioDatagramConnector;


public class UdpClient { 
	private static final String CHARSET = "GBK";
	private IoSession     session = null;
	private UdpCallback   callback;
	private String        serverIp;
	private int           port;
	private String        startTag;
	private String        endTag;
	private String        errorStartTag;

	
	public UdpClient(String ip, int port, UdpCallback callback, String startTag, String endTag, String errorStartTag) {
		this.callback      = callback;
		this.serverIp      = ip;
		this.port          = port;
		this.startTag      = startTag;
		this.endTag        = endTag;
		this.errorStartTag = errorStartTag;
	}

	public void send(final String s) throws Exception {
		NioDatagramConnector connect = new NioDatagramConnector(); 
		connect.setConnectTimeoutMillis(8000);
		connect.getSessionConfig().setSendBufferSize(2048);
		connect.getSessionConfig().setReadBufferSize(1024*64);
		connect.getSessionConfig().setReceiveBufferSize(1024*64);
		connect.setHandler(new UDPClientHandler());
        
		try{
			ConnectFuture future = connect.connect(new InetSocketAddress(serverIp,port)); 
			future.awaitUninterruptibly();
			session = future.getSession(); 
			//增加连接建立完成后的监听器。 
			//若在建立完成后才添加监听器，监听器将马上执行 
			future.addListener(new IoFutureListener<ConnectFuture>(){ 
				
	            public void operationComplete(ConnectFuture future) {
	            	try {
	            		if( future.isConnected() ){
		                    try {
		                        sendData(s);
		                    } catch (InterruptedException e) {
		                        e.printStackTrace();
		                    }
		                } else {
		                    System.out.println(("Not connected...exiting"));
		                    throw new Exception("premsg:Not connected...exiting");
		                }
					} catch (Exception e) {
						e.printStackTrace();
					}
	            }
	        });
		}catch(Exception e){
			e.printStackTrace();
			throw new Exception("premsg:" + e.getMessage());
		}finally{
			if(session!=null){
        	    session.getCloseFuture().awaitUninterruptibly(10000);
        	}
		}
		connect.dispose();
	}
	
    private void sendData(String s) throws  Exception {
    	Charset c = Charset.forName(CHARSET);
        IoBuffer buffer = IoBuffer.allocate(8);
        buffer.setAutoExpand(true);
		buffer.putString(s, c.newEncoder());
        buffer.flip();
        session.write(buffer);
        
        //因为是UDP，客户端需主动关闭连接
        //session.close(false);
    }
    
	class UDPClientHandler extends IoHandlerAdapter{
		private boolean flag          = false;
		private StringBuffer sb       = new StringBuffer();
		private int startTagLen       = startTag.length();
		private int endTagLen         = endTag.length();
		private int errorStartTagLen  = errorStartTag.length();
		
		@Override
		public void messageReceived(IoSession session, Object message) throws Exception {
			
			IoBuffer buffer = (IoBuffer)message;
			byte[] array = buffer.array();
			
			// 每次接收的数据
			if (array != null) {
				sb.append(new String(array, Charset.forName(CHARSET)).trim().replace("\r\n", ""));
				// System.out.println("客户端接收(单次):" + new String(array, Charset.forName(CHARSET)).trim().replace("\r\n", ""));
			}

			// 合并多次接收的数据
			int len = sb.length();
			if (sb.substring(0, startTagLen).equals(startTag) && sb.substring(len - endTagLen, len).equals(endTag)) {
				callback.receive(sb.toString());
				Log.d("udp","rev ==>> :客户端接收(正常):" + sb.toString());
				session.close(true);
			} else if (sb.substring(0, errorStartTagLen).equals(errorStartTag)) {
				callback.receive(sb.toString());
				Log.d("udp","rev ==>> " + System.currentTimeMillis() + ":客户端接收(出错):" + sb.toString());
				session.close(true);
			}

			flag = true;
		}

		@Override
		public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
			if (!flag) {
				callback.receive("");
				flag = true;
			}
		}

		@Override
		public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
			cause.printStackTrace();
			if (!flag) {
				callback.receive("");
				flag = true;
			}
			session.close(true);
		}
		

		@Override
		public void messageSent(IoSession session, Object message) throws Exception {
			System.out.println("messageSent..." );
		}

		@Override
		public void sessionClosed(IoSession session) throws Exception {
			System.out.println("sessionClosed...");
			if (!flag) {
				callback.receive("");
				flag = true;
			}
		}

		@Override
		public void sessionCreated(IoSession session) throws Exception {
			System.out.println("sessionCreated...");
		}

		@Override
		public void sessionOpened(IoSession session) throws Exception {
			System.out.println("sessionOpened...");
		}
		
	}
	
	public static void main(String[] args) {
		String jscx = "<gs ver=\"1.0\" function=\"技师资料查询\" mode=\"request\">"
		+"<ArtNo></ArtNo>"
		+"<Status></Status>"
		+"<Onduty></Onduty>"
		+"<Columns>artno,status</Columns>"
		+ "</gs>";
		
		for (int i = 0; i < 1; i++) {
			System.out.println("iiiiiiiiiiiiiiiiiiiii:" + i);
			UdpCallback c = new UdpCallback() {
				
				@Override
				public void receive(String s) {
					System.out.println("客户端接到到的数据啊：" + s);
				}
			};
			System.out.println("send ==>> " + System.currentTimeMillis());
			try {
				new UdpClient("172.16.1.222", 9999, c, "<gs", "</gs>", "Msg").send(jscx);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("getmsg:" + e.getMessage());
			}
		}
		
	}
}